Data
Parameters
suffix = "01_22"
data_to_read = ""
functions
source_from_github(repositoy = "DEG_functions",version = "0.2.24")
ℹ SHA-1 hash of file is a183df1c565702ecd8ed338bb2abfb0e13415d8e
source_from_github(repositoy = "HMSC_functions",version = "0.1.02",script_name = "functions.R")
ℹ SHA-1 hash of file is 53b38a31ba24251739c046cc18406d5b3ec0f896
Enrichment analysis HMSC vs ACC
patient.ident = all_acc_cancer_cells$patient.ident %>% as.data.frame()
patient.ident[,1] = as.character(patient.ident[,1])
patient.ident[patient.ident[,1] == "ACC1",] = "HMSC"
patient.ident[,1] = as.factor(patient.ident[,1])
all_acc_cancer_cells = AddMetaData(object = all_acc_cancer_cells,metadata = patient.ident,col.name = "patient.ident")
all_acc_cancer_cells = SetIdent(all_acc_cancer_cells, value ="patient.ident")
acc_deg <- FindMarkers(all_acc_cancer_cells, ident.1 = "HMSC",logfc.threshold = 1.5,features = VariableFeatures(all_acc_cancer_cells))
enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells),fdr_Cutoff = 0.01,ident.1 = "HMSC",ident.2 = "ACC",show_by = 1)

cell cycle filtering
conflict_prefer("intersect", "base")
[conflicted] Will prefer base::intersect over any other package.
Before cc filtering
FeaturePlot(object = all_acc_cancer_cells,features = hallmark_name) + ggtitle("Before cc filtering") & scale_color_gradientn(colours = plasma(n = 10, direction = -1), limits = c(min_threshold, max_threshold))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.

After cc filtering
FeaturePlot(object = all_acc_cancer_cells_ccFiltered,features = hallmark_name) + ggtitle("After cc filtering") & scale_color_gradientn(colours = plasma(n = 10, direction = -1), limits = c(min_threshold, max_threshold))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.

Enrichment analysis filtered HMSC vs ACC
patient.ident = all_acc_cancer_cells_ccFiltered$patient.ident %>% as.data.frame()
patient.ident[,1] = as.character(patient.ident[,1])
patient.ident[patient.ident[,1] == "ACC1",] = "HMSC"
patient.ident[,1] = as.factor(patient.ident[,1])
all_acc_cancer_cells_ccFiltered = AddMetaData(object = all_acc_cancer_cells_ccFiltered,metadata = patient.ident,col.name = "patient.ident")
all_acc_cancer_cells_ccFiltered = SetIdent(all_acc_cancer_cells_ccFiltered, value ="patient.ident")
acc_deg <- FindMarkers(all_acc_cancer_cells_ccFiltered, ident.1 = "HMSC",logfc.threshold = 1.5,features = VariableFeatures(all_acc_cancer_cells_ccFiltered))
enrichment_analysis(acc_deg,background = VariableFeatures(all_acc_cancer_cells_ccFiltered),fdr_Cutoff = 0.01,ident.1 = "HMSC",ident.2 = "ACC",show_by = 1)

MYB expression
all_acc_cancer_cells = SetIdent(object = all_acc_cancer_cells,value = "patient.ident") #active snn graph
FeaturePlot(object = all_acc_cancer_cells,features = "MYB",label = T)

CNV
new.cluster.ids <- c("cancer", #0
"cancer", #1
"CAF", #2
"cancer", #3
"Endothelial", #4
"cancer", #5
"cancer", #6
"CAF", #7
"CAF", #8
"CAF", #9
"cancer", #10
"CAF", #11
"cancer", #12
"cancer", #13
"cancer", #14
"cancer", #15
"cancer", #16
"WBC", #17
"CAF" #18
)
#rename idents:
acc_all_cells = SetIdent(object = acc_all_cells,value = "RNA_snn_res.1") #active snn graph
names(new.cluster.ids) <- levels(acc_all_cells) #add snn graph levels to new.cluster.ids
acc_all_cells@meta.data[["seurat_clusters"]] = acc_all_cells@meta.data[["RNA_snn_res.1"]]
acc_all_cells = SetIdent(object = acc_all_cells,value = "seurat_clusters")
acc_all_cells <- RenameIdents(acc_all_cells, new.cluster.ids)
# divide "cancer" into patients:
cell_types = acc_all_cells@active.ident %>% as.data.frame()
cell_types[,1]<- as.character(cell_types[,1])
cell_types = cbind(cell_types,acc_all_cells$patient.ident) %>% setnames(old = names(.),
new = c('cell_type','patient'))
cell_types[cell_types$cell_type == "cancer",] = cell_types[cell_types$cell_type == "cancer",2]
# hmsc_rows = (startsWith(x = rownames(cell_types),prefix = "ACC.plate2") | startsWith(x = rownames(cell_types),prefix = "ACC1.")) & cell_types[,1] == "cancer"
# acc_rows = !(startsWith(x = rownames(cell_types),prefix = "ACC.plate2") | startsWith(x = rownames(cell_types),prefix = "ACC1.")) & cell_types[,1] == "cancer"
# cell_types[,1][hmsc_rows] = "HMSC"
# cell_types[,1][acc_rows] = "ACC"
#add to metadata:
cell_types[,2] = NULL
cell_types[cell_types$cell_type == "ACC1",] = "HMSC"
acc_all_cells = AddMetaData(object =acc_all_cells ,metadata = cell_types,col.name = "cell.type")
CNV UMAP

CNV plot
## {-}
Original score
original_myo_genes = c( "TP63", "TP73", "CAV1", "CDH3", "KRT5", "KRT14", "ACTA2", "TAGLN", "MYLK", "DKK3")
original_lum_genes = c("KIT", "EHF", "ELF5", "KRT7", "CLDN3", "CLDN4", "CD24", "LGALS3", "LCN2", "SLPI" )
myoscore=apply(all_acc_cancer_cells@assays[["RNA"]][original_myo_genes,],2,mean)
lescore=apply(all_acc_cancer_cells@assays[["RNA"]][original_lum_genes,],2,mean)
all_acc_cancer_cells=AddMetaData(all_acc_cancer_cells,lescore-myoscore,"luminal_over_myo")
FeaturePlot(object = all_acc_cancer_cells,features = "luminal_over_myo")

data = FetchData(object = all_acc_cancer_cells,vars = "luminal_over_myo")
print(
data %>%
ggplot(aes( x=luminal_over_myo)) +
geom_density()
)

only_acc_cancer_cells = subset(x = all_acc_cancer_cells,patient.ident !="HMSC")
myo_cells_num = subset(x = only_acc_cancer_cells,luminal_over_myo >1) %>% ncol() /ncol(all_acc_cancer_cells)
lum_cells_num = subset(x = only_acc_cancer_cells,luminal_over_myo <(-1)) %>% ncol()/ncol(all_acc_cancer_cells)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
geom_bar(stat="identity") + ggtitle("ACC cell types")

myoscore=apply(acc1_cancer_cells@assays[["RNA"]][original_myo_genes,],2,mean)
lescore=apply(acc1_cancer_cells@assays[["RNA"]][original_lum_genes,],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,lescore-myoscore,"luminal_over_myo")
FeaturePlot(object = acc1_cancer_cells,features = "luminal_over_myo")

data = FetchData(object = acc1_cancer_cells,vars = "luminal_over_myo")
print(
data %>%
ggplot(aes( x=luminal_over_myo)) +
geom_density()
)

myo_cells_num = subset(x = acc1_cancer_cells,luminal_over_myo >0) %>% ncol() /ncol(acc1_cancer_cells)
lum_cells_num = subset(x = acc1_cancer_cells,luminal_over_myo <(0)) %>% ncol()/ncol(acc1_cancer_cells)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
geom_bar(stat="identity") + ggtitle("ACC cell types")

0.35 Most correlated score
Myo genes
myo_protein_markers = c("CNN1", "TP63","ACTA2")
# undebug(top_correlated)
top_myo = top_correlated(dataset = acc1_cancer_cells, genes = myo_protein_markers,threshold = 0.35)
print("Number of genes = " %>% paste(length(top_myo)))
[1] "Number of genes = 20"
message("Names of genes:")
Names of genes:
top_myo %>% head(30)
[1] "COL16A1" "RP1-39G22.4" "ACTG2" "CD200" "MYLK" "TP63" "KCNMB1" "ADAMTS2" "LOXL2"
[10] "TPM2" "CLIC3" "SNCG" "ACTA2" "TAGLN" "A2M" "NGFR" "CNN1" "PPP1R14A"
[19] "MYL9" "POM121L9P"
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_myo,original_myo_genes)
[1] "MYLK" "TP63" "ACTA2" "TAGLN"
myo_enrich_res = genes_vec_enrichment(genes = top_myo,background = rownames(acc1_cancer_cells),homer = T,title = "myo top enrichment",custom_pathways = luminal_gs)

myo_enrich_res
Lum genes
lum_protein_markers = c("KIT")
top_lum = top_correlated(dataset = acc1_cancer_cells, genes = lum_protein_markers,threshold = 0.35)
Warning in cor(expression %>% t(), markers_average) :
the standard deviation is zero
print("Number of genes = " %>% paste(length(top_lum)))
[1] "Number of genes = 22"
message("Names of genes:")
Names of genes:
top_lum %>% head(30)
[1] "FBXO44" "USP48" "MPC2" "SLC19A2" "ATL2" "B3GNT2" "AC093162.5"
[8] "MAP2" "KIT" "GLRB" "EFNA5" "PCDHGB7" "SLC29A1" "SASH1"
[15] "ALDH3B2" "CCND1" "RP11-254B13.1" "VSIG10" "NDFIP2" "SUSD6" "SPPL2A"
[22] "DSC2"
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_lum,original_lum_genes)
[1] "KIT"
lum_enrich_res = genes_vec_enrichment(genes = top_lum,background = rownames(acc1_cancer_cells),homer = T,title = "lum top enrichment",custom_pathways = luminal_gs)

lum_enrich_res
enriched genes score
rownames(lum_enrich_res) = lum_enrich_res$pathway_name
lum_enriched_genes = lum_enrich_res[1,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,lum_protein_markers) #add original markers
rownames(myo_enrich_res) = myo_enrich_res$pathway_name
myo_enriched_genes = myo_enrich_res[1,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,myo_protein_markers) #add original markers
myoscore=apply(acc1_cancer_cells@assays[["RNA"]]@data[myo_enriched_genes,],2,mean)
lescore=apply(acc1_cancer_cells@assays[["RNA"]]@data[lum_enriched_genes,],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,lescore-myoscore,"enriched_luminal_over_myo")
FeaturePlot(object = acc1_cancer_cells,features = "enriched_luminal_over_myo")

data = FetchData(object = acc1_cancer_cells,vars = "enriched_luminal_over_myo")
print(
data %>%
ggplot(aes( x=enriched_luminal_over_myo)) +
geom_density()
)

myo_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo >(-2.5)) %>% ncol() /ncol(acc1_cancer_cells)
lum_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo <(-2.5)) %>% ncol()/ncol(acc1_cancer_cells)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
geom_bar(stat="identity") + ggtitle("ACC cell types")

0.2 Most correlated score
myo Genes
myo_protein_markers = c("CNN1", "TP63","ACTA2")
top_myo = top_correlated(dataset = acc1_cancer_cells, genes = myo_protein_markers,threshold = 0.2)
print("Number of genes = " %>% paste(length(top_myo)))
[1] "Number of genes = 473"
message("Names of genes:")
Names of genes:
top_myo %>% head(30)
[1] "MIR429" "EXOSC10" "PLOD1" "TNFRSF8" "PDPN" "FBLIM1" "RP11-276H7.3"
[8] "HSPG2" "EPHA8" "IFNLR1" "GRHL3" "RP3-426I6.6" "SDC3" "RP11-490K7.1"
[15] "RP11-73M7.1" "TINAGL1" "COL16A1" "RP1-117O3.2" "RP11-435D7.3" "RP1-39G22.4" "SCMH1"
[22] "RP5-850O15.4" "RP5-866L20.3" "NEXN" "RP4-714D9.2" "RP5-837M10.3" "RP5-964H19.1" "CSF1"
[29] "RP11-498A13.1" "RP11-96K19.2"
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_myo,original_myo_genes)
[1] "MYLK" "TP63" "ACTA2" "DKK3" "TAGLN" "CDH3"
myo_enrich_res = genes_vec_enrichment(genes = top_myo,background = rownames(acc1_cancer_cells),homer = T,title = "myo top enrichment",custom_pathways = luminal_gs)

myo_enrich_res
Lum Genes
lum_protein_markers = c("KIT")
top_lum = top_correlated(dataset = acc1_cancer_cells, genes = lum_protein_markers,threshold = 0.2)
Warning in cor(expression %>% t(), markers_average) :
the standard deviation is zero
print("Number of genes = " %>% paste(length(top_lum)))
[1] "Number of genes = 1535"
message("Names of genes:")
Names of genes:
top_lum %>% head(30)
[1] "RP11-206L10.11" "HES4" "RP11-54O7.18" "CPTP" "RP3-395M20.8" "TNFRSF14" "RPL22"
[8] "ICMT" "ERRFI1" "RERE" "H6PD" "TMEM201" "NMNAT1" "UBE4B"
[15] "APITD1-CORT" "CENPS" "RP4-635E18.7" "FBXO2" "FBXO44" "UQCRHL" "MST1P2"
[22] "SDHB" "PADI2" "ARHGEF10L" "AKR7A2" "TMCO4" "EIF4G3" "USP48"
[29] "NIPAL3" "PIGV"
message("Genes that also apeared in the original score:")
Genes that also apeared in the original score:
base::intersect(top_lum,original_lum_genes)
[1] "KIT" "EHF" "LGALS3"
lum_enrich_res = genes_vec_enrichment(genes = top_lum,background = rownames(acc1_cancer_cells),homer = T,title = "lum top enrichment",custom_pathways = luminal_gs)

lum_enrich_res
correlated genes in original score
myo_intersected = intersect(top_myo,original_myo_genes)
lum_intersected = intersect(top_lum,original_lum_genes)
message("genes in myo score:")
genes in myo score:
myo_intersected
[1] "MYLK" "TP63" "ACTA2" "DKK3" "TAGLN" "CDH3"
message("genes in lum score:")
genes in lum score:
lum_intersected
[1] "KIT" "EHF" "LGALS3"
myoscore=apply(acc1_cancer_cells@assays[["RNA"]]@data[c("MYLK","TP63" ,"ACTA2", "DKK3", "TAGLN", "CDH3" ),],2,mean)
lescore=apply(acc1_cancer_cells@assays[["RNA"]]@data[c("KIT" ,"EHF", "LGALS3"),],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,lescore-myoscore,"enriched_luminal_over_myo")
FeaturePlot(object = acc1_cancer_cells,features = "enriched_luminal_over_myo")

data = FetchData(object = acc1_cancer_cells,vars = "enriched_luminal_over_myo")
print(
data %>%
ggplot(aes( x=enriched_luminal_over_myo)) +
geom_density()
)

myo_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo >(2)) %>% ncol() /ncol(acc1_cancer_cells)
lum_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo <(1)) %>% ncol()/ncol(acc1_cancer_cells)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
geom_bar(stat="identity") + ggtitle("ACC cell types")

enriched genes
rownames(lum_enrich_res) = lum_enrich_res$pathway_name
lum_enriched_genes = lum_enrich_res[3,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,lum_protein_markers) #add original markers
rownames(myo_enrich_res) = myo_enrich_res$pathway_name
myo_enriched_genes = myo_enrich_res[3,"geneID"] %>% strsplit(split = "/") %>% .[[1]] %>% c(.,myo_protein_markers) #add original markers
message("genes in myo score:")
genes in myo score:
myo_enriched_genes
[1] "FBLIM1" "NEXN" "NMNAT2" "MYLK" "CCDC50" "IGFBP7" "RAI14" "ARAP3" "SPARC" "CALD1" "LOXL2" "COL5A1"
[13] "ACTA2" "DKK3" "MSRB3" "COL4A1" "ACTN1" "TPM1" "TGFB1I1" "ADORA2B" "MXRA7" "CNN1" "TP63" "ACTA2"
message("genes in lum score:")
genes in lum score:
lum_enriched_genes
[1] "PADI2" "PATJ" "PEX11B" "APH1A" "C1orf43" "EFNA4" "NECTIN4" "SCYL3" "ELF3"
[10] "SOX13" "IRF6" "MED28" "EPB41L4A" "RGL2" "C6orf132" "TPD52L1" "ICA1" "MACC1"
[19] "TRPS1" "FAM83H" "RASEF" "ARRDC1" "COMMD3" "ANK3" "GSTO2" "PDCD4" "EHF"
[28] "ALDH3B2" "SHANK2" "SORL1" "FKBP4" "PTPN6" "DUSP16" "RERG" "ADCY6" "ERBB3"
[37] "ERP29" "SUSD6" "RPS6KA5" "SPINT1" "FEM1B" "TLE3" "SCAMP2" "CLN3" "ADGRG1"
[46] "ATP2C2" "GGT6" "MYO1D" "ST6GALNAC2" "CYB5A" "BLVRB" "VRK3" "SYCP2" "TMPRSS2"
[55] "LIMK2" "KIT"
myoscore=apply(acc1_cancer_cells@assays[["RNA"]]@data[myo_enriched_genes,],2,mean)
lescore=apply(acc1_cancer_cells@assays[["RNA"]]@data[lum_enriched_genes,],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,lescore-myoscore,"enriched_luminal_over_myo")
FeaturePlot(object = acc1_cancer_cells,features = "enriched_luminal_over_myo")

data = FetchData(object = acc1_cancer_cells,vars = "enriched_luminal_over_myo")
print(
data %>%
ggplot(aes( x=enriched_luminal_over_myo)) +
geom_density()
)

myo_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo >(0)) %>% ncol() /ncol(acc1_cancer_cells)
lum_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo <(-1)) %>% ncol()/ncol(acc1_cancer_cells)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
geom_bar(stat="identity") + ggtitle("ACC cell types")

enriched genes and in original score
myo_enriched_genes = myo_enriched_genes[myo_enriched_genes %in% original_myo_genes]
lum_enriched_genes = lum_enriched_genes[lum_enriched_genes %in% original_lum_genes]
message("genes in myo score:")
genes in myo score:
myo_enriched_genes
[1] "MYLK" "ACTA2" "DKK3" "TP63" "ACTA2"
message("genes in lum score:")
genes in lum score:
lum_enriched_genes
[1] "EHF" "KIT"
myoscore=apply(acc1_cancer_cells@assays[["RNA"]]@data[myo_enriched_genes,],2,mean)
lescore=apply(acc1_cancer_cells@assays[["RNA"]]@data[lum_enriched_genes,],2,mean)
acc1_cancer_cells=AddMetaData(acc1_cancer_cells,lescore-myoscore,"enriched_luminal_over_myo")
FeaturePlot(object = acc1_cancer_cells,features = "enriched_luminal_over_myo")

data = FetchData(object = acc1_cancer_cells,vars = "enriched_luminal_over_myo")
print(
data %>%
ggplot(aes( x=enriched_luminal_over_myo)) +
geom_density()
)

myo_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo >(2)) %>% ncol() /ncol(acc1_cancer_cells)
lum_cells_num = subset(x = acc1_cancer_cells,enriched_luminal_over_myo <(2)) %>% ncol()/ncol(acc1_cancer_cells)
df = data.frame(cell_type = c("myo_cells","lum_cells"),percentage = c(myo_cells_num,lum_cells_num))
ggplot(data=df, aes(x=cell_type, y=percentage)) +
geom_bar(stat="identity") + ggtitle("ACC cell types")

HPV
Only HMSC cancer cells:
HPV33_P3 = fread("./Data/HPV33_P3.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P3.df = HPV33_P3 %>% mutate(
plate = gsub(x =HPV33_P3$plate, replacement = "",pattern = "_.*$")
%>% gsub(pattern = "-P",replacement = ".P")
%>% gsub(pattern = "-",replacement = "_",)
)
HPV33_P3.df = HPV33_P3.df %>% dplyr::filter(HPV33_P3.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P3.df) <- HPV33_P3.df$plate
HPV33_P3.df$plate = NULL
HPV33_P2 = fread("./Data/HPV33_P2.txt",col.names = c("plate","reads")) %>% as.data.frame()
HPV33_P2.df = HPV33_P2 %>% mutate(
plate = gsub(x =HPV33_P2$plate, replacement = "",pattern = "_.*$")
%>% gsub(pattern = "plate2-",replacement = "plate2_",)
%>% gsub(pattern = "-",replacement = "\\.",)
)
HPV33_P2.df = HPV33_P2.df %>% dplyr::filter(HPV33_P2.df$plate %in% colnames(acc1_cancer_cells))
rownames(HPV33_P2.df) <- HPV33_P2.df$plate
HPV33_P2.df$plate = NULL
HPV33 = rbind(HPV33_P3.df,HPV33_P2.df)
acc1_cancer_cells = AddMetaData(object = acc1_cancer_cells,metadata = HPV33,col.name = "HPV33.reads")
FeaturePlot(acc1_cancer_cells,features = "HPV33.reads",max.cutoff = 40)

data = FetchData(object = acc1_cancer_cells,vars = "HPV33.reads")
print(
data %>%
ggplot(aes( x=HPV33.reads)) +
geom_density()
)

LS0tCnRpdGxlOiAiVGl0bGUiCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQotLS0KCiMjIERhdGEKCmBgYHtyfQphY2MxX2NhbmNlcl9jZWxscyA9IHJlYWRSRFMoIi4vRGF0YS9hY2MxX2NhbmNlcl9jZWxsc18xNUtuQ291bnRfVjMuUkRTIikKYWxsX2FjY19jYW5jZXJfY2VsbHMgPSByZWFkUkRTKCIuL0RhdGEvYWNjX2NhbmNlcl9jZWxsc19WMy5SRFMiKQphY2NfYWxsX2NlbGxzID0gcmVhZFJEUygiLi9EYXRhL2FjY190cG1fbkNvdW50X21pdG9fbm8xNDZfMTVrX3dpdGhfQUNDMV8uUkRTIikKbHVtaW5hbF9wYXRod2F5cyA9IGMoIkNIQVJBRkVfQlJFQVNUX0NBTkNFUl9MVU1JTkFMX1ZTX0JBU0FMX0ROIiwiQ0hBUkFGRV9CUkVBU1RfQ0FOQ0VSX0xVTUlOQUxfVlNfQkFTQUxfVVAiLCJDSEFSQUZFX0JSRUFTVF9DQU5DRVJfTFVNSU5BTF9WU19NRVNFTkNIWU1BTF9ETiIsIkNIQVJBRkVfQlJFQVNUX0NBTkNFUl9MVU1JTkFMX1ZTX01FU0VOQ0hZTUFMX1VQIiwiSFVQRVJfQlJFQVNUX0JBU0FMX1ZTX0xVTUlOQUxfRE4iLCJMSU1fTUFNTUFSWV9MVU1JTkFMX1BST0dFTklUT1JfVVAiLCJTTUlEX0JSRUFTVF9DQU5DRVJfTFVNSU5BTF9CX1VQIiApCgojIGFkZCBsdW1pbmFsIHBhdGh3YXlzCmx1bWluYWxfZ3MgPSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIikgJT4lYXMuZGF0YS5mcmFtZSgpICU+JSBkcGx5cjo6ZmlsdGVyKGdzX25hbWUgJWluJSBsdW1pbmFsX3BhdGh3YXlzKSU+JSBkcGx5cjo6ZGlzdGluY3QoZ3NfbmFtZSwgZ2VuZV9zeW1ib2wpICU+JSBhcy5kYXRhLmZyYW1lKCkKCmBgYAoKIyMgUGFyYW1ldGVycwoKYGBge3Igd2FybmluZz1GQUxTRX0Kc3VmZml4ID0gIjAxXzIyIgpkYXRhX3RvX3JlYWQgPSAiIgpgYGAKCgojIyBmdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiREVHX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjIuMjQiKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gIkhNU0NfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuMS4wMiIsc2NyaXB0X25hbWUgPSAiZnVuY3Rpb25zLlIiKQpgYGAKCgojIyBFbnJpY2htZW50IGFuYWx5c2lzIEhNU0MgdnMgQUNDCmBgYHtyIGZpZy53aWR0aD04LCBlY2hvPVRSVUUscmVzdWx0cz0naGlkZScsZmlnLmtlZXA9J2FsbCd9CnBhdGllbnQuaWRlbnQgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyRwYXRpZW50LmlkZW50ICU+JSBhcy5kYXRhLmZyYW1lKCkKcGF0aWVudC5pZGVudFssMV0gPSBhcy5jaGFyYWN0ZXIocGF0aWVudC5pZGVudFssMV0pCnBhdGllbnQuaWRlbnRbcGF0aWVudC5pZGVudFssMV0gPT0gIkFDQzEiLF0gPSAiSE1TQyIKcGF0aWVudC5pZGVudFssMV0gPSBhcy5mYWN0b3IocGF0aWVudC5pZGVudFssMV0pCmFsbF9hY2NfY2FuY2VyX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBwYXRpZW50LmlkZW50LGNvbC5uYW1lID0gInBhdGllbnQuaWRlbnQiKQphbGxfYWNjX2NhbmNlcl9jZWxscyA9IFNldElkZW50KGFsbF9hY2NfY2FuY2VyX2NlbGxzLCB2YWx1ZSA9InBhdGllbnQuaWRlbnQiKQphY2NfZGVnIDwtIEZpbmRNYXJrZXJzKGFsbF9hY2NfY2FuY2VyX2NlbGxzLCBpZGVudC4xID0gIkhNU0MiLGxvZ2ZjLnRocmVzaG9sZCA9IDEuNSxmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHMpKQplbnJpY2htZW50X2FuYWx5c2lzKGFjY19kZWcsYmFja2dyb3VuZCA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHMpLGZkcl9DdXRvZmYgPSAwLjAxLGlkZW50LjEgPSAiSE1TQyIsaWRlbnQuMiA9ICJBQ0MiLHNob3dfYnkgPSAxKQpgYGAKCiMjIGNlbGwgY3ljbGUgZmlsdGVyaW5nIHsudGFic2V0fQoKYGBge3Igd2FybmluZz1GQUxTRX0KbGlicmFyeShHU0VBQmFzZSkKbGlicmFyeShjb25mbGljdGVkKQpjb25mbGljdF9wcmVmZXIobmFtZSA9ICJpbnRlcnNlY3QiLCB3aW5uZXIgPSAiYmFzZSIscXVpZXQgPSBUKQpoYWxsbWFya19uYW1lID0gIkdPX01JVE9USUNfQ0VMTF9DWUNMRSIKZ2VuZXNldHMgID1nZXRHbXQoIi4vRGF0YS9oLmFsbC52Ny4wLnN5bWJvbHMucGx1c2NjLmdtdCIpCnZhcl9mZWF0dXJlcz1hbGxfYWNjX2NhbmNlcl9jZWxsc0Bhc3NheXMkUk5BQHZhci5mZWF0dXJlcwpnZW5lSWRzPSBnZW5lc2V0c1tbaGFsbG1hcmtfbmFtZV1dQGdlbmVJZHMKc2NvcmUgPC0gYXBwbHkoYWxsX2FjY19jYW5jZXJfY2VsbHNAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChnZW5lSWRzLHZhcl9mZWF0dXJlcyksXSwyLG1lYW4pCmFsbF9hY2NfY2FuY2VyX2NlbGxzPUFkZE1ldGFEYXRhKGFsbF9hY2NfY2FuY2VyX2NlbGxzLHNjb3JlLGhhbGxtYXJrX25hbWUpCgojZmlsdGVyOgphbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkPWFsbF9hY2NfY2FuY2VyX2NlbGxzWyxhbGxfYWNjX2NhbmNlcl9jZWxsc0BtZXRhLmRhdGFbW2hhbGxtYXJrX25hbWVdXTwgMC4zXQoKCm1pbl90aHJlc2hvbGQgPSBtaW4oYWxsX2FjY19jYW5jZXJfY2VsbHMkR09fTUlUT1RJQ19DRUxMX0NZQ0xFKQptYXhfdGhyZXNob2xkID0gbWF4KGFsbF9hY2NfY2FuY2VyX2NlbGxzJEdPX01JVE9USUNfQ0VMTF9DWUNMRSkKYGBgCgoKIyMjIEJlZm9yZSBjYyBmaWx0ZXJpbmcKCgpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSBoYWxsbWFya19uYW1lKSArIGdndGl0bGUoIkJlZm9yZSBjYyBmaWx0ZXJpbmciKSAgJiBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IHBsYXNtYShuID0gMTAsIGRpcmVjdGlvbiA9IC0xKSwgbGltaXRzID0gYyhtaW5fdGhyZXNob2xkLCBtYXhfdGhyZXNob2xkKSkKYGBgCgojIyMgQWZ0ZXIgY2MgZmlsdGVyaW5nCgpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCxmZWF0dXJlcyA9IGhhbGxtYXJrX25hbWUpICsgZ2d0aXRsZSgiQWZ0ZXIgY2MgZmlsdGVyaW5nIikgJiBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3VycyA9IHBsYXNtYShuID0gMTAsIGRpcmVjdGlvbiA9IC0xKSwgbGltaXRzID0gYyhtaW5fdGhyZXNob2xkLCBtYXhfdGhyZXNob2xkKSkKYGBgCiMjIHstfQoKIyMgRW5yaWNobWVudCBhbmFseXNpcyBmaWx0ZXJlZCBITVNDIHZzIEFDQwpgYGB7ciBmaWcud2lkdGg9OCwgZWNobz1UUlVFLHJlc3VsdHM9J2hpZGUnLGZpZy5rZWVwPSdhbGwnfQpwYXRpZW50LmlkZW50ID0gYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCRwYXRpZW50LmlkZW50ICU+JSBhcy5kYXRhLmZyYW1lKCkKcGF0aWVudC5pZGVudFssMV0gPSBhcy5jaGFyYWN0ZXIocGF0aWVudC5pZGVudFssMV0pCnBhdGllbnQuaWRlbnRbcGF0aWVudC5pZGVudFssMV0gPT0gIkFDQzEiLF0gPSAiSE1TQyIKcGF0aWVudC5pZGVudFssMV0gPSBhcy5mYWN0b3IocGF0aWVudC5pZGVudFssMV0pCmFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQgPSBBZGRNZXRhRGF0YShvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxsc19jY0ZpbHRlcmVkLG1ldGFkYXRhID0gcGF0aWVudC5pZGVudCxjb2wubmFtZSA9ICJwYXRpZW50LmlkZW50IikKYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCA9IFNldElkZW50KGFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQsIHZhbHVlID0icGF0aWVudC5pZGVudCIpCmFjY19kZWcgPC0gRmluZE1hcmtlcnMoYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCwgaWRlbnQuMSA9ICJITVNDIixsb2dmYy50aHJlc2hvbGQgPSAxLjUsZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKGFsbF9hY2NfY2FuY2VyX2NlbGxzX2NjRmlsdGVyZWQpKQplbnJpY2htZW50X2FuYWx5c2lzKGFjY19kZWcsYmFja2dyb3VuZCA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsX2FjY19jYW5jZXJfY2VsbHNfY2NGaWx0ZXJlZCksZmRyX0N1dG9mZiA9IDAuMDEsaWRlbnQuMSA9ICJITVNDIixpZGVudC4yID0gIkFDQyIsc2hvd19ieSA9IDEpCmBgYAoKIyMgTVlCIGV4cHJlc3Npb24KCmBgYHtyIGZpZy53aWR0aD0xMH0KYWxsX2FjY19jYW5jZXJfY2VsbHMgPSBTZXRJZGVudChvYmplY3QgPSBhbGxfYWNjX2NhbmNlcl9jZWxscyx2YWx1ZSA9ICJwYXRpZW50LmlkZW50IikgI2FjdGl2ZSBzbm4gZ3JhcGgKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWxsX2FjY19jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAiTVlCIixsYWJlbCA9IFQpCmBgYAoKIyMgQ05WIHsudGFic2V0fQoKCgpgYGB7cn0KI3NldCBjZWxsIHR5cGVzCm5ldy5jbHVzdGVyLmlkcyA8LSBjKCJjYW5jZXIiLCAjMAogICAgICAgICAgICAgICAgICAgICAiY2FuY2VyIiwgIzEKICAgICAgICAgICAgICAgICAgICAgIkNBRiIsICMyCiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMwogICAgICAgICAgICAgICAgICAgICAiRW5kb3RoZWxpYWwiLCAjNAogICAgICAgICAgICAgICAgICAgICAiY2FuY2VyIiwgIzUKICAgICAgICAgICAgICAgICAgICAgImNhbmNlciIsICM2CiAgICAgICAgICAgICAgICAgICAgICJDQUYiLCAjNwogICAgICAgICAgICAgICAgICAgICAiQ0FGIiwgIzgKICAgICAgICAgICAgICAgICAgICAgIkNBRiIsICM5CiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMTAKICAgICAgICAgICAgICAgICAgICAgIkNBRiIsICMxMQogICAgICAgICAgICAgICAgICAgICAiY2FuY2VyIiwgIzEyCiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMTMKICAgICAgICAgICAgICAgICAgICAgImNhbmNlciIsICMxNAogICAgICAgICAgICAgICAgICAgICAiY2FuY2VyIiwgIzE1CiAgICAgICAgICAgICAgICAgICAgICJjYW5jZXIiLCAjMTYKICAgICAgICAgICAgICAgICAgICAgIldCQyIsICMxNwogICAgICAgICAgICAgICAgICAgICAiQ0FGIiAjMTgKICAgICAgICAgICAgICAgICAgICAgKQpgYGAKCgpgYGB7ciBmaWcuc2hvdz0naGlkZSd9CiNyZW5hbWUgaWRlbnRzOgphY2NfYWxsX2NlbGxzID0gU2V0SWRlbnQob2JqZWN0ID0gYWNjX2FsbF9jZWxscyx2YWx1ZSA9ICJSTkFfc25uX3Jlcy4xIikgI2FjdGl2ZSBzbm4gZ3JhcGgKbmFtZXMobmV3LmNsdXN0ZXIuaWRzKSA8LSBsZXZlbHMoYWNjX2FsbF9jZWxscykgI2FkZCBzbm4gZ3JhcGggbGV2ZWxzIHRvIG5ldy5jbHVzdGVyLmlkcwphY2NfYWxsX2NlbGxzQG1ldGEuZGF0YVtbInNldXJhdF9jbHVzdGVycyJdXSA9IGFjY19hbGxfY2VsbHNAbWV0YS5kYXRhW1siUk5BX3Nubl9yZXMuMSJdXQphY2NfYWxsX2NlbGxzID0gU2V0SWRlbnQob2JqZWN0ID0gYWNjX2FsbF9jZWxscyx2YWx1ZSA9ICJzZXVyYXRfY2x1c3RlcnMiKQphY2NfYWxsX2NlbGxzIDwtIFJlbmFtZUlkZW50cyhhY2NfYWxsX2NlbGxzLCBuZXcuY2x1c3Rlci5pZHMpIAoKIyBkaXZpZGUgImNhbmNlciIgaW50byBwYXRpZW50czoKY2VsbF90eXBlcyA9IGFjY19hbGxfY2VsbHNAYWN0aXZlLmlkZW50ICU+JSBhcy5kYXRhLmZyYW1lKCkKY2VsbF90eXBlc1ssMV08LSBhcy5jaGFyYWN0ZXIoY2VsbF90eXBlc1ssMV0pCmNlbGxfdHlwZXMgPSBjYmluZChjZWxsX3R5cGVzLGFjY19hbGxfY2VsbHMkcGF0aWVudC5pZGVudCkgJT4lIHNldG5hbWVzKG9sZCA9IG5hbWVzKC4pLCAKICAgICAgICAgbmV3ID0gYygnY2VsbF90eXBlJywncGF0aWVudCcpKQpjZWxsX3R5cGVzW2NlbGxfdHlwZXMkY2VsbF90eXBlID09ICJjYW5jZXIiLF0gPSBjZWxsX3R5cGVzW2NlbGxfdHlwZXMkY2VsbF90eXBlID09ICJjYW5jZXIiLDJdCgoKIyBobXNjX3Jvd3MgPSAoc3RhcnRzV2l0aCh4ID0gcm93bmFtZXMoY2VsbF90eXBlcykscHJlZml4ID0gIkFDQy5wbGF0ZTIiKSB8IHN0YXJ0c1dpdGgoeCA9IHJvd25hbWVzKGNlbGxfdHlwZXMpLHByZWZpeCA9ICJBQ0MxLiIpKSAmIGNlbGxfdHlwZXNbLDFdID09ICJjYW5jZXIiIAojIGFjY19yb3dzID0gIShzdGFydHNXaXRoKHggPSByb3duYW1lcyhjZWxsX3R5cGVzKSxwcmVmaXggPSAiQUNDLnBsYXRlMiIpIHwgc3RhcnRzV2l0aCh4ID0gcm93bmFtZXMoY2VsbF90eXBlcykscHJlZml4ID0gIkFDQzEuIikpICYgY2VsbF90eXBlc1ssMV0gPT0gImNhbmNlciIgCiMgY2VsbF90eXBlc1ssMV1baG1zY19yb3dzXSAgPSAiSE1TQyIKIyBjZWxsX3R5cGVzWywxXVthY2Nfcm93c10gID0gIkFDQyIKCiNhZGQgdG8gbWV0YWRhdGE6CmNlbGxfdHlwZXNbLDJdID0gTlVMTCAKY2VsbF90eXBlc1tjZWxsX3R5cGVzJGNlbGxfdHlwZSA9PSAiQUNDMSIsXSA9ICJITVNDIgphY2NfYWxsX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID1hY2NfYWxsX2NlbGxzICxtZXRhZGF0YSA9IGNlbGxfdHlwZXMsY29sLm5hbWUgPSAiY2VsbC50eXBlIikKYGBgCiMjIyBDTlYgVU1BUCAKCmBgYHtyIGZpZy53aWR0aD0xMH0KbGlicmFyeShpbmZlcmNudikKbGlicmFyeSh0aWR5dmVyc2UpCmFjY19hbm5vdGF0aW9uICA9IGFzLmRhdGEuZnJhbWUoYWNjX2FsbF9jZWxsc0BtZXRhLmRhdGFbLCJjZWxsLnR5cGUiLGRyb3AgPSBGXSkKYWNjX2Fubm90YXRpb24gPSBhY2NfYW5ub3RhdGlvbiAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJvcmlnLmlkZW50IikgCmFjY19hbm5vdGF0aW9uID0gYWNjX2Fubm90YXRpb24gJT4lIG11dGF0ZShvcmlnLmlkZW50ID0gZ3N1Yih4ID0gYWNjX2Fubm90YXRpb24kb3JpZy5pZGVudCxwYXR0ZXJuID0gIlxcLiIsIHJlcGxhY2VtZW50ID0gIi0iKSAlPiUgCiAgZ3N1YihwYXR0ZXJuID0gIl8iLCByZXBsYWNlbWVudCA9ICItIikpCiAgCgp3cml0ZS50YWJsZShhY2NfYW5ub3RhdGlvbiwgIi4vRGF0YS9pbmZlckNOVi9hY2NfYW5ub3RhdGlvbi50eHQiLCBhcHBlbmQgPSBGQUxTRSwgCiAgICAgICAgICAgIHNlcCA9ICJcdCIsIGRlYyA9ICIuIixyb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRikKCmluZmVyY252X29iaiA9IENyZWF0ZUluZmVyY252T2JqZWN0KHJhd19jb3VudHNfbWF0cml4PSIuL0RhdGEvaW5mZXJDTlYvYWxsLjRpY252LnR4dCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uc19maWxlPSIuL0RhdGEvaW5mZXJDTlYvYWNjX2Fubm90YXRpb24udHh0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsaW09Ilx0IixnZW5lX29yZGVyX2ZpbGU9Ii4vRGF0YS9pbmZlckNOVi9nZW5jb2RlX3YxOV9nZW5lX3Bvcy50eHQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxyZWZfZ3JvdXBfbmFtZXM9YygiQ0FGIiwgIkVuZG90aGVsaWFsIiwgIldCQyIpKSAjZ3JvdXBzIG9mIG5vcm1hbCBjZWxscwoKaW5mZXJjbnZfb2JqX2RlZmF1bHQgPSBpbmZlcmNudjo6cnVuKGluZmVyY252X29iaiwgY3V0b2ZmPTEsIG91dF9kaXI9Jy4vRGF0YS9pbmZlckNOVi9pbmZlcmNudl9vdXRwdXQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9ieV9ncm91cHM9VCwgcGxvdF9zdGVwcz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbm9pc2U9VFJVRSwgSE1NPUZBTFNFLCBub19wcmVsaW1fcGxvdD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG5nX3Jlcz0zMDApCnBsb3RfY252KGluZmVyY252X29ial9kZWZhdWx0LCBvdXRwdXRfZm9ybWF0ID0gInBuZyIsICB3cml0ZV9leHByX21hdHJpeCA9IEZBTFNFLG91dF9kaXIgPSAiLi9EYXRhL2luZmVyQ05WLyIscG5nX3Jlcwk9ODAwLG9ic190aXRsZSA9ICJNYWxpZ25hbnQgY2VsbHMiLHJlZl90aXRsZSA9ICJOb3JtYWwgY2VsbHMiKQoKCmNsdXN0ZXIuaW5mbz1GZXRjaERhdGEoYWNjX2FsbF9jZWxscyxjKCJpZGVudCIsIm9yaWcuaWRlbnQiLCJVTUFQXzEiLCJVTUFQXzIiLCJuQ291bnRfUk5BIiwibkZlYXR1cmVfUk5BIiwicGVyY2VudC5tdCIsInBhdGllbnQuaWRlbnQiLCJzZXVyYXRfY2x1c3RlcnMiKSkKY2x1c3Rlci5pbmZvJGNlbGw9cm93bmFtZXMoY2x1c3Rlci5pbmZvKQoKbGlicmFyeShsaW1tYSkKc21vb3RoZWQ9YXBwbHkoaW5mZXJjbnZfb2JqX2RlZmF1bHRAZXhwci5kYXRhLDIsdHJpY3ViZU1vdmluZ0F2ZXJhZ2UsIHNwYW49MC4wMSkKY25zaWc9c3FydChhcHBseSgoc21vb3RoZWQtMSleMiwyLG1lYW4pKQp1bWFwPWNsdXN0ZXIuaW5mbwpuYW1lcyhjbnNpZyk9dW1hcCRjZWxsCgphY2NfYWxsX2NlbGxzIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjY19hbGxfY2VsbHMsIG1ldGFkYXRhID0gY25zaWcsIGNvbC5uYW1lID0gImNvcHludW1iZXIiKQphY2NfYWxsX2NlbGxzID0gU2V0SWRlbnQob2JqZWN0ID0gYWNjX2FsbF9jZWxscyx2YWx1ZSA9ICJjZWxsLnR5cGUiKQpGZWF0dXJlUGxvdChhY2NfYWxsX2NlbGxzLCAiY29weW51bWJlciIscHQuc2l6ZSA9IDEsIGNvbHMgPSBjKCJsaWdodGJsdWUiLCJvcmFuZ2UiLCJyZWQiLCJkYXJrcmVkIiksbGFiZWwgPSBULHJlcGVsID0gVCkKYGBgCgoKIyMjIENOViBwbG90IAoKIVtDTlYgcGxvdF0oL3NjaS9sYWJzL3lvdGFtZC9sYWJfc2hhcmUvYXZpc2hhaS53aXplbC9SX3Byb2plY3RzL0hNU0MvRGF0YS9pbmZlckNOVi9pbmZlcmNudi5wbmcpCiMjIHstfQoKIyMgT3JpZ2luYWwgc2NvcmUKYGBge3J9Cm9yaWdpbmFsX215b19nZW5lcyA9IGMoICJUUDYzIiwgIlRQNzMiLCAiQ0FWMSIsICJDREgzIiwgIktSVDUiLCAiS1JUMTQiLCAiQUNUQTIiLCAiVEFHTE4iLCAiTVlMSyIsICJES0szIikKb3JpZ2luYWxfbHVtX2dlbmVzID0gYygiS0lUIiwgIkVIRiIsICJFTEY1IiwgIktSVDciLCAiQ0xETjMiLCAiQ0xETjQiLCAiQ0QyNCIsICJMR0FMUzMiLCAiTENOMiIsICJTTFBJIiApCmBgYAoKYGBge3J9Cm15b3Njb3JlPWFwcGx5KGFsbF9hY2NfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXVtvcmlnaW5hbF9teW9fZ2VuZXMsXSwyLG1lYW4pCmxlc2NvcmU9YXBwbHkoYWxsX2FjY19jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dW29yaWdpbmFsX2x1bV9nZW5lcyxdLDIsbWVhbikKYWxsX2FjY19jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWxsX2FjY19jYW5jZXJfY2VsbHMsbGVzY29yZS1teW9zY29yZSwibHVtaW5hbF9vdmVyX215byIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gImx1bWluYWxfb3Zlcl9teW8iKQpkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLHZhcnMgPSAibHVtaW5hbF9vdmVyX215byIpCnByaW50KAogIGRhdGEgJT4lIAogIGdncGxvdChhZXMoIHg9bHVtaW5hbF9vdmVyX215bykpICsgCiAgZ2VvbV9kZW5zaXR5KCkgCikKYGBgCmBgYHtyfQpvbmx5X2FjY19jYW5jZXJfY2VsbHMgPSBzdWJzZXQoeCA9IGFsbF9hY2NfY2FuY2VyX2NlbGxzLHBhdGllbnQuaWRlbnQgIT0iSE1TQyIpCm15b19jZWxsc19udW0gPSBzdWJzZXQoeCA9IG9ubHlfYWNjX2NhbmNlcl9jZWxscyxsdW1pbmFsX292ZXJfbXlvID4xKSAlPiUgbmNvbCgpIC9uY29sKGFsbF9hY2NfY2FuY2VyX2NlbGxzKQpsdW1fY2VsbHNfbnVtID0gc3Vic2V0KHggPSBvbmx5X2FjY19jYW5jZXJfY2VsbHMsbHVtaW5hbF9vdmVyX215byA8KC0xKSkgJT4lIG5jb2woKS9uY29sKGFsbF9hY2NfY2FuY2VyX2NlbGxzKQpkZiA9IGRhdGEuZnJhbWUoY2VsbF90eXBlID0gYygibXlvX2NlbGxzIiwibHVtX2NlbGxzIikscGVyY2VudGFnZSA9IGMobXlvX2NlbGxzX251bSxsdW1fY2VsbHNfbnVtKSkKZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PWNlbGxfdHlwZSwgeT1wZXJjZW50YWdlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyBnZ3RpdGxlKCJBQ0MgY2VsbCB0eXBlcyIpCmBgYAoKYGBge3J9Cm15b3Njb3JlPWFwcGx5KGFjYzFfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXVtvcmlnaW5hbF9teW9fZ2VuZXMsXSwyLG1lYW4pCmxlc2NvcmU9YXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dW29yaWdpbmFsX2x1bV9nZW5lcyxdLDIsbWVhbikKYWNjMV9jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWNjMV9jYW5jZXJfY2VsbHMsbGVzY29yZS1teW9zY29yZSwibHVtaW5hbF9vdmVyX215byIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gImx1bWluYWxfb3Zlcl9teW8iKQpkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSAibHVtaW5hbF9vdmVyX215byIpCnByaW50KAogICAgZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKCB4PWx1bWluYWxfb3Zlcl9teW8pKSArIAogICAgZ2VvbV9kZW5zaXR5KCkgCiAgKQpgYGAKYGBge3J9Cm15b19jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLGx1bWluYWxfb3Zlcl9teW8gPjApICU+JSBuY29sKCkgL25jb2woYWNjMV9jYW5jZXJfY2VsbHMpCmx1bV9jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLGx1bWluYWxfb3Zlcl9teW8gPCgwKSkgJT4lIG5jb2woKS9uY29sKGFjYzFfY2FuY2VyX2NlbGxzKQpkZiA9IGRhdGEuZnJhbWUoY2VsbF90eXBlID0gYygibXlvX2NlbGxzIiwibHVtX2NlbGxzIikscGVyY2VudGFnZSA9IGMobXlvX2NlbGxzX251bSxsdW1fY2VsbHNfbnVtKSkKZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PWNlbGxfdHlwZSwgeT1wZXJjZW50YWdlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyBnZ3RpdGxlKCJBQ0MgY2VsbCB0eXBlcyIpCmBgYAojIyAwLjM1IE1vc3QgY29ycmVsYXRlZCBzY29yZSB7LnRhYnNldH0KCiMjIyBNeW8gZ2VuZXMKCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBjb2xsYXBzZT1UfQpteW9fcHJvdGVpbl9tYXJrZXJzID0gYygiQ05OMSIsICJUUDYzIiwiQUNUQTIiKQojIHVuZGVidWcodG9wX2NvcnJlbGF0ZWQpCnRvcF9teW8gID0gdG9wX2NvcnJlbGF0ZWQoZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzLCBnZW5lcyA9IG15b19wcm90ZWluX21hcmtlcnMsdGhyZXNob2xkID0gMC4zNSkKcHJpbnQoIk51bWJlciBvZiBnZW5lcyA9ICIgJT4lIHBhc3RlKGxlbmd0aCh0b3BfbXlvKSkpCm1lc3NhZ2UoIk5hbWVzIG9mIGdlbmVzOiIpCnRvcF9teW8gJT4lIGhlYWQoMzApCm1lc3NhZ2UoIkdlbmVzIHRoYXQgYWxzbyBhcGVhcmVkIGluIHRoZSBvcmlnaW5hbCBzY29yZToiKQpiYXNlOjppbnRlcnNlY3QodG9wX215byxvcmlnaW5hbF9teW9fZ2VuZXMpIApgYGAKYGBge3J9Cm15b19lbnJpY2hfcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3BfbXlvLGJhY2tncm91bmQgPSByb3duYW1lcyhhY2MxX2NhbmNlcl9jZWxscyksaG9tZXIgPSBULHRpdGxlID0gIm15byB0b3AgZW5yaWNobWVudCIsY3VzdG9tX3BhdGh3YXlzID0gbHVtaW5hbF9ncykKbXlvX2VucmljaF9yZXMKYGBgCiMjIyBMdW0gZ2VuZXMKYGBge3J9Cmx1bV9wcm90ZWluX21hcmtlcnMgPSBjKCJLSVQiKQp0b3BfbHVtICA9IHRvcF9jb3JyZWxhdGVkKGRhdGFzZXQgPSBhY2MxX2NhbmNlcl9jZWxscywgZ2VuZXMgPSBsdW1fcHJvdGVpbl9tYXJrZXJzLHRocmVzaG9sZCA9IDAuMzUpCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgPSAiICU+JSBwYXN0ZShsZW5ndGgodG9wX2x1bSkpKQptZXNzYWdlKCJOYW1lcyBvZiBnZW5lczoiKQp0b3BfbHVtICU+JSBoZWFkKDMwKQptZXNzYWdlKCJHZW5lcyB0aGF0IGFsc28gYXBlYXJlZCBpbiB0aGUgb3JpZ2luYWwgc2NvcmU6IikKYmFzZTo6aW50ZXJzZWN0KHRvcF9sdW0sb3JpZ2luYWxfbHVtX2dlbmVzKSAKYGBgCgpgYGB7cn0KbHVtX2VucmljaF9yZXMgPSBnZW5lc192ZWNfZW5yaWNobWVudChnZW5lcyA9IHRvcF9sdW0sYmFja2dyb3VuZCA9IHJvd25hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSxob21lciA9IFQsdGl0bGUgPSAibHVtIHRvcCBlbnJpY2htZW50IixjdXN0b21fcGF0aHdheXMgPSBsdW1pbmFsX2dzKQpsdW1fZW5yaWNoX3JlcwpgYGAKIyMjIHRvcCBjb3JyZWxhdGVkIHNjb3JlCmBgYHtyfQpteW9zY29yZT1hcHBseShhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1bdG9wX215byxdLDIsbWVhbikKbGVzY29yZT1hcHBseShhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1bdG9wX2x1bSxdLDIsbWVhbikKYWNjMV9jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWNjMV9jYW5jZXJfY2VsbHMsbGVzY29yZS1teW9zY29yZSwidG9wX2Nvcl9sdW1pbmFsX292ZXJfbXlvIikKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAidG9wX2Nvcl9sdW1pbmFsX292ZXJfbXlvIikKCmRhdGEgPSBGZXRjaERhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsdmFycyA9ICJ0b3BfY29yX2x1bWluYWxfb3Zlcl9teW8iKQpwcmludCgKICBkYXRhICU+JSAKICBnZ3Bsb3QoYWVzKCB4PXRvcF9jb3JfbHVtaW5hbF9vdmVyX215bykpICsgCiAgZ2VvbV9kZW5zaXR5KCkgCikKICBteW9fY2VsbHNfbnVtID0gc3Vic2V0KHggPSBhY2MxX2NhbmNlcl9jZWxscyx0b3BfY29yX2x1bWluYWxfb3Zlcl9teW8gPjApICU+JSBuY29sKCkgL25jb2woYWxsX2FjY19jYW5jZXJfY2VsbHMpCmx1bV9jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLHRvcF9jb3JfbHVtaW5hbF9vdmVyX215byA8KDApKSAlPiUgbmNvbCgpL25jb2woYWxsX2FjY19jYW5jZXJfY2VsbHMpCmRmID0gZGF0YS5mcmFtZShjZWxsX3R5cGUgPSBjKCJteW9fY2VsbHMiLCJsdW1fY2VsbHMiKSxwZXJjZW50YWdlID0gYyhteW9fY2VsbHNfbnVtLGx1bV9jZWxsc19udW0pKQpnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9Y2VsbF90eXBlLCB5PXBlcmNlbnRhZ2UpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIGdndGl0bGUoIkFDQyBjZWxsIHR5cGVzIikKCmBgYAoKCiMjIyAgZW5yaWNoZWQgZ2VuZXMgc2NvcmUKYGBge3J9CnJvd25hbWVzKGx1bV9lbnJpY2hfcmVzKSA9IGx1bV9lbnJpY2hfcmVzJHBhdGh3YXlfbmFtZQpsdW1fZW5yaWNoZWRfZ2VuZXMgPSBsdW1fZW5yaWNoX3Jlc1sxLCJnZW5lSUQiXSAlPiUgc3Ryc3BsaXQoc3BsaXQgPSAiLyIpICU+JSAuW1sxXV0gJT4lIGMoLixsdW1fcHJvdGVpbl9tYXJrZXJzKSAjYWRkIG9yaWdpbmFsIG1hcmtlcnMKYGBgCgpgYGB7cn0Kcm93bmFtZXMobXlvX2VucmljaF9yZXMpID0gbXlvX2VucmljaF9yZXMkcGF0aHdheV9uYW1lCm15b19lbnJpY2hlZF9nZW5lcyA9IG15b19lbnJpY2hfcmVzWzEsImdlbmVJRCJdICU+JSBzdHJzcGxpdChzcGxpdCA9ICIvIikgJT4lIC5bWzFdXSAlPiUgYyguLG15b19wcm90ZWluX21hcmtlcnMpICNhZGQgb3JpZ2luYWwgbWFya2VycwpgYGAKCmBgYHtyfQpteW9zY29yZT1hcHBseShhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1AZGF0YVtteW9fZW5yaWNoZWRfZ2VuZXMsXSwyLG1lYW4pCmxlc2NvcmU9YXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dQGRhdGFbbHVtX2VucmljaGVkX2dlbmVzLF0sMixtZWFuKQphY2MxX2NhbmNlcl9jZWxscz1BZGRNZXRhRGF0YShhY2MxX2NhbmNlcl9jZWxscyxsZXNjb3JlLW15b3Njb3JlLCJlbnJpY2hlZF9sdW1pbmFsX292ZXJfbXlvIikKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAiZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byIpCgpkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSAiZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byIpCnByaW50KAogIGRhdGEgJT4lIAogIGdncGxvdChhZXMoIHg9ZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215bykpICsgCiAgZ2VvbV9kZW5zaXR5KCkgCikKCm15b19jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLGVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8gPigtMi41KSkgJT4lIG5jb2woKSAvbmNvbChhY2MxX2NhbmNlcl9jZWxscykKbHVtX2NlbGxzX251bSA9IHN1YnNldCh4ID0gYWNjMV9jYW5jZXJfY2VsbHMsZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byA8KC0yLjUpKSAlPiUgbmNvbCgpL25jb2woYWNjMV9jYW5jZXJfY2VsbHMpCmRmID0gZGF0YS5mcmFtZShjZWxsX3R5cGUgPSBjKCJteW9fY2VsbHMiLCJsdW1fY2VsbHMiKSxwZXJjZW50YWdlID0gYyhteW9fY2VsbHNfbnVtLGx1bV9jZWxsc19udW0pKQpnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9Y2VsbF90eXBlLCB5PXBlcmNlbnRhZ2UpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIGdndGl0bGUoIkFDQyBjZWxsIHR5cGVzIikKYGBgCgoKIyMgey19CgoKIyMgIDAuMiBNb3N0IGNvcnJlbGF0ZWQgc2NvcmUgey50YWJzZXR9CgojIyMgIG15byBHZW5lcwoKCmBgYHtyIHdhcm5pbmc9RkFMU0V9Cm15b19wcm90ZWluX21hcmtlcnMgPSBjKCJDTk4xIiwgIlRQNjMiLCJBQ1RBMiIpCnRvcF9teW8gID0gdG9wX2NvcnJlbGF0ZWQoZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzLCBnZW5lcyA9IG15b19wcm90ZWluX21hcmtlcnMsdGhyZXNob2xkID0gMC4yKQpwcmludCgiTnVtYmVyIG9mIGdlbmVzID0gIiAlPiUgcGFzdGUobGVuZ3RoKHRvcF9teW8pKSkKbWVzc2FnZSgiTmFtZXMgb2YgZ2VuZXM6IikKdG9wX215byAlPiUgaGVhZCgzMCkKbWVzc2FnZSgiR2VuZXMgdGhhdCBhbHNvIGFwZWFyZWQgaW4gdGhlIG9yaWdpbmFsIHNjb3JlOiIpCmJhc2U6OmludGVyc2VjdCh0b3BfbXlvLG9yaWdpbmFsX215b19nZW5lcykgCmBgYAoKYGBge3J9Cm15b19lbnJpY2hfcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3BfbXlvLGJhY2tncm91bmQgPSByb3duYW1lcyhhY2MxX2NhbmNlcl9jZWxscyksaG9tZXIgPSBULHRpdGxlID0gIm15byB0b3AgZW5yaWNobWVudCIsY3VzdG9tX3BhdGh3YXlzID0gbHVtaW5hbF9ncykKbXlvX2VucmljaF9yZXMKYGBgCiMjIyAgTHVtIEdlbmVzCgpgYGB7cn0KbHVtX3Byb3RlaW5fbWFya2VycyA9IGMoIktJVCIpCnRvcF9sdW0gID0gdG9wX2NvcnJlbGF0ZWQoZGF0YXNldCA9IGFjYzFfY2FuY2VyX2NlbGxzLCBnZW5lcyA9IGx1bV9wcm90ZWluX21hcmtlcnMsdGhyZXNob2xkID0gMC4yKQpwcmludCgiTnVtYmVyIG9mIGdlbmVzID0gIiAlPiUgcGFzdGUobGVuZ3RoKHRvcF9sdW0pKSkKbWVzc2FnZSgiTmFtZXMgb2YgZ2VuZXM6IikKdG9wX2x1bSAlPiUgaGVhZCgzMCkKbWVzc2FnZSgiR2VuZXMgdGhhdCBhbHNvIGFwZWFyZWQgaW4gdGhlIG9yaWdpbmFsIHNjb3JlOiIpCmJhc2U6OmludGVyc2VjdCh0b3BfbHVtLG9yaWdpbmFsX2x1bV9nZW5lcykgCmBgYAoKYGBge3J9Cmx1bV9lbnJpY2hfcmVzID0gZ2VuZXNfdmVjX2VucmljaG1lbnQoZ2VuZXMgPSB0b3BfbHVtLGJhY2tncm91bmQgPSByb3duYW1lcyhhY2MxX2NhbmNlcl9jZWxscyksaG9tZXIgPSBULHRpdGxlID0gImx1bSB0b3AgZW5yaWNobWVudCIsY3VzdG9tX3BhdGh3YXlzID0gbHVtaW5hbF9ncykKbHVtX2VucmljaF9yZXMKYGBgCiMjIyAgY29ycmVsYXRlZCBnZW5lcyBpbiBvcmlnaW5hbCBzY29yZQpgYGB7cn0KbXlvX2ludGVyc2VjdGVkID0gaW50ZXJzZWN0KHRvcF9teW8sb3JpZ2luYWxfbXlvX2dlbmVzKSAKbHVtX2ludGVyc2VjdGVkID0gaW50ZXJzZWN0KHRvcF9sdW0sb3JpZ2luYWxfbHVtX2dlbmVzKSAKbWVzc2FnZSgiZ2VuZXMgaW4gbXlvIHNjb3JlOiIpCm15b19pbnRlcnNlY3RlZAoKbWVzc2FnZSgiZ2VuZXMgaW4gbHVtIHNjb3JlOiIpCmx1bV9pbnRlcnNlY3RlZAoKCm15b3Njb3JlPWFwcGx5KGFjYzFfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXUBkYXRhW2MoIk1ZTEsiLCJUUDYzIiAsIkFDVEEyIiwgIkRLSzMiLCAiVEFHTE4iLCAiQ0RIMyIgKSxdLDIsbWVhbikKbGVzY29yZT1hcHBseShhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1AZGF0YVtjKCJLSVQiICwiRUhGIiwgICJMR0FMUzMiKSxdLDIsbWVhbikKYWNjMV9jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWNjMV9jYW5jZXJfY2VsbHMsbGVzY29yZS1teW9zY29yZSwiZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gImVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8iKQoKZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gImVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8iKQpwcmludCgKICBkYXRhICU+JSAKICBnZ3Bsb3QoYWVzKCB4PWVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8pKSArIAogIGdlb21fZGVuc2l0eSgpIAopCgpteW9fY2VsbHNfbnVtID0gc3Vic2V0KHggPSBhY2MxX2NhbmNlcl9jZWxscyxlbnJpY2hlZF9sdW1pbmFsX292ZXJfbXlvID4oMikpICU+JSBuY29sKCkgL25jb2woYWNjMV9jYW5jZXJfY2VsbHMpCmx1bV9jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLGVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8gPCgxKSkgJT4lIG5jb2woKS9uY29sKGFjYzFfY2FuY2VyX2NlbGxzKQpkZiA9IGRhdGEuZnJhbWUoY2VsbF90eXBlID0gYygibXlvX2NlbGxzIiwibHVtX2NlbGxzIikscGVyY2VudGFnZSA9IGMobXlvX2NlbGxzX251bSxsdW1fY2VsbHNfbnVtKSkKZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PWNlbGxfdHlwZSwgeT1wZXJjZW50YWdlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyBnZ3RpdGxlKCJBQ0MgY2VsbCB0eXBlcyIpCmBgYAoKIyMjIGVucmljaGVkIGdlbmVzCmBgYHtyfQpyb3duYW1lcyhsdW1fZW5yaWNoX3JlcykgPSBsdW1fZW5yaWNoX3JlcyRwYXRod2F5X25hbWUKbHVtX2VucmljaGVkX2dlbmVzID0gbHVtX2VucmljaF9yZXNbMywiZ2VuZUlEIl0gJT4lIHN0cnNwbGl0KHNwbGl0ID0gIi8iKSAlPiUgLltbMV1dICU+JSBjKC4sbHVtX3Byb3RlaW5fbWFya2VycykgI2FkZCBvcmlnaW5hbCBtYXJrZXJzCmBgYAoKYGBge3J9CnJvd25hbWVzKG15b19lbnJpY2hfcmVzKSA9IG15b19lbnJpY2hfcmVzJHBhdGh3YXlfbmFtZQpteW9fZW5yaWNoZWRfZ2VuZXMgPSBteW9fZW5yaWNoX3Jlc1szLCJnZW5lSUQiXSAlPiUgc3Ryc3BsaXQoc3BsaXQgPSAiLyIpICU+JSAuW1sxXV0gJT4lIGMoLixteW9fcHJvdGVpbl9tYXJrZXJzKSAjYWRkIG9yaWdpbmFsIG1hcmtlcnMKYGBgCgpgYGB7cn0KbWVzc2FnZSgiZ2VuZXMgaW4gbXlvIHNjb3JlOiIpCm15b19lbnJpY2hlZF9nZW5lcwoKbWVzc2FnZSgiZ2VuZXMgaW4gbHVtIHNjb3JlOiIpCmx1bV9lbnJpY2hlZF9nZW5lcwoKbXlvc2NvcmU9YXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dQGRhdGFbbXlvX2VucmljaGVkX2dlbmVzLF0sMixtZWFuKQpsZXNjb3JlPWFwcGx5KGFjYzFfY2FuY2VyX2NlbGxzQGFzc2F5c1tbIlJOQSJdXUBkYXRhW2x1bV9lbnJpY2hlZF9nZW5lcyxdLDIsbWVhbikKYWNjMV9jYW5jZXJfY2VsbHM9QWRkTWV0YURhdGEoYWNjMV9jYW5jZXJfY2VsbHMsbGVzY29yZS1teW9zY29yZSwiZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byIpCkZlYXR1cmVQbG90KG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gImVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8iKQoKZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gImVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8iKQpwcmludCgKICBkYXRhICU+JSAKICBnZ3Bsb3QoYWVzKCB4PWVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8pKSArIAogIGdlb21fZGVuc2l0eSgpIAopCgpteW9fY2VsbHNfbnVtID0gc3Vic2V0KHggPSBhY2MxX2NhbmNlcl9jZWxscyxlbnJpY2hlZF9sdW1pbmFsX292ZXJfbXlvID4oMCkpICU+JSBuY29sKCkgL25jb2woYWNjMV9jYW5jZXJfY2VsbHMpCmx1bV9jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLGVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8gPCgtMSkpICU+JSBuY29sKCkvbmNvbChhY2MxX2NhbmNlcl9jZWxscykKZGYgPSBkYXRhLmZyYW1lKGNlbGxfdHlwZSA9IGMoIm15b19jZWxscyIsImx1bV9jZWxscyIpLHBlcmNlbnRhZ2UgPSBjKG15b19jZWxsc19udW0sbHVtX2NlbGxzX251bSkpCmdncGxvdChkYXRhPWRmLCBhZXMoeD1jZWxsX3R5cGUsIHk9cGVyY2VudGFnZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgZ2d0aXRsZSgiQUNDIGNlbGwgdHlwZXMiKQpgYGAKCgoKCiMjIyBlbnJpY2hlZCBnZW5lcyBhbmQgaW4gb3JpZ2luYWwgc2NvcmUKYGBge3J9Cm15b19lbnJpY2hlZF9nZW5lcyA9IG15b19lbnJpY2hlZF9nZW5lc1tteW9fZW5yaWNoZWRfZ2VuZXMgJWluJSBvcmlnaW5hbF9teW9fZ2VuZXNdCmx1bV9lbnJpY2hlZF9nZW5lcyA9IGx1bV9lbnJpY2hlZF9nZW5lc1tsdW1fZW5yaWNoZWRfZ2VuZXMgJWluJSBvcmlnaW5hbF9sdW1fZ2VuZXNdCgpgYGAKCmBgYHtyfQoKbWVzc2FnZSgiZ2VuZXMgaW4gbXlvIHNjb3JlOiIpCm15b19lbnJpY2hlZF9nZW5lcwoKbWVzc2FnZSgiZ2VuZXMgaW4gbHVtIHNjb3JlOiIpCmx1bV9lbnJpY2hlZF9nZW5lcwpteW9zY29yZT1hcHBseShhY2MxX2NhbmNlcl9jZWxsc0Bhc3NheXNbWyJSTkEiXV1AZGF0YVtteW9fZW5yaWNoZWRfZ2VuZXMsXSwyLG1lYW4pCmxlc2NvcmU9YXBwbHkoYWNjMV9jYW5jZXJfY2VsbHNAYXNzYXlzW1siUk5BIl1dQGRhdGFbbHVtX2VucmljaGVkX2dlbmVzLF0sMixtZWFuKQphY2MxX2NhbmNlcl9jZWxscz1BZGRNZXRhRGF0YShhY2MxX2NhbmNlcl9jZWxscyxsZXNjb3JlLW15b3Njb3JlLCJlbnJpY2hlZF9sdW1pbmFsX292ZXJfbXlvIikKRmVhdHVyZVBsb3Qob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsZmVhdHVyZXMgPSAiZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byIpCgpkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IGFjYzFfY2FuY2VyX2NlbGxzLHZhcnMgPSAiZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byIpCnByaW50KAogIGRhdGEgJT4lIAogIGdncGxvdChhZXMoIHg9ZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215bykpICsgCiAgZ2VvbV9kZW5zaXR5KCkgCikKCm15b19jZWxsc19udW0gPSBzdWJzZXQoeCA9IGFjYzFfY2FuY2VyX2NlbGxzLGVucmljaGVkX2x1bWluYWxfb3Zlcl9teW8gPigyKSkgJT4lIG5jb2woKSAvbmNvbChhY2MxX2NhbmNlcl9jZWxscykKbHVtX2NlbGxzX251bSA9IHN1YnNldCh4ID0gYWNjMV9jYW5jZXJfY2VsbHMsZW5yaWNoZWRfbHVtaW5hbF9vdmVyX215byA8KDIpKSAlPiUgbmNvbCgpL25jb2woYWNjMV9jYW5jZXJfY2VsbHMpCmRmID0gZGF0YS5mcmFtZShjZWxsX3R5cGUgPSBjKCJteW9fY2VsbHMiLCJsdW1fY2VsbHMiKSxwZXJjZW50YWdlID0gYyhteW9fY2VsbHNfbnVtLGx1bV9jZWxsc19udW0pKQpnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9Y2VsbF90eXBlLCB5PXBlcmNlbnRhZ2UpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIGdndGl0bGUoIkFDQyBjZWxsIHR5cGVzIikKYGBgCmBgYHtyfQoKYGBgCgojIyB7LX0KCgojIEhQVgoKT25seSBITVNDIGNhbmNlciBjZWxsczoKCmBgYHtyfQpIUFYzM19QMyA9IGZyZWFkKCIuL0RhdGEvSFBWMzNfUDMudHh0Iixjb2wubmFtZXMgPSBjKCJwbGF0ZSIsInJlYWRzIikpICU+JSBhcy5kYXRhLmZyYW1lKCkKSFBWMzNfUDMuZGYgPSBIUFYzM19QMyAlPiUgbXV0YXRlKAogIHBsYXRlID0gZ3N1Yih4ID1IUFYzM19QMyRwbGF0ZSwgcmVwbGFjZW1lbnQgPSAiIixwYXR0ZXJuID0gIl8uKiQiKSAKICAlPiUgZ3N1YihwYXR0ZXJuID0gIi1QIixyZXBsYWNlbWVudCA9ICIuUCIpIAogICU+JSBnc3ViKHBhdHRlcm4gPSAiLSIscmVwbGFjZW1lbnQgPSAiXyIsKQogICkKSFBWMzNfUDMuZGYgPSBIUFYzM19QMy5kZiAlPiUgZHBseXI6OmZpbHRlcihIUFYzM19QMy5kZiRwbGF0ZSAlaW4lIGNvbG5hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSkKcm93bmFtZXMoSFBWMzNfUDMuZGYpICA8LSBIUFYzM19QMy5kZiRwbGF0ZQpIUFYzM19QMy5kZiRwbGF0ZSA9IE5VTEwKCgpIUFYzM19QMiA9IGZyZWFkKCIuL0RhdGEvSFBWMzNfUDIudHh0Iixjb2wubmFtZXMgPSBjKCJwbGF0ZSIsInJlYWRzIikpICU+JSBhcy5kYXRhLmZyYW1lKCkKSFBWMzNfUDIuZGYgPSBIUFYzM19QMiAlPiUgbXV0YXRlKAogIHBsYXRlID0gZ3N1Yih4ID1IUFYzM19QMiRwbGF0ZSwgcmVwbGFjZW1lbnQgPSAiIixwYXR0ZXJuID0gIl8uKiQiKSAKICAlPiUgZ3N1YihwYXR0ZXJuID0gInBsYXRlMi0iLHJlcGxhY2VtZW50ID0gInBsYXRlMl8iLCkKICAlPiUgZ3N1YihwYXR0ZXJuID0gIi0iLHJlcGxhY2VtZW50ID0gIlxcLiIsKQogICkKSFBWMzNfUDIuZGYgPSBIUFYzM19QMi5kZiAlPiUgZHBseXI6OmZpbHRlcihIUFYzM19QMi5kZiRwbGF0ZSAlaW4lIGNvbG5hbWVzKGFjYzFfY2FuY2VyX2NlbGxzKSkKcm93bmFtZXMoSFBWMzNfUDIuZGYpICA8LSBIUFYzM19QMi5kZiRwbGF0ZQpIUFYzM19QMi5kZiRwbGF0ZSA9IE5VTEwKCkhQVjMzID0gcmJpbmQoSFBWMzNfUDMuZGYsSFBWMzNfUDIuZGYpCmFjYzFfY2FuY2VyX2NlbGxzID0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjMV9jYW5jZXJfY2VsbHMsbWV0YWRhdGEgPSBIUFYzMyxjb2wubmFtZSA9ICJIUFYzMy5yZWFkcyIpCkZlYXR1cmVQbG90KGFjYzFfY2FuY2VyX2NlbGxzLGZlYXR1cmVzID0gIkhQVjMzLnJlYWRzIixtYXguY3V0b2ZmID0gNDApCmBgYApgYGB7cn0KZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBhY2MxX2NhbmNlcl9jZWxscyx2YXJzID0gIkhQVjMzLnJlYWRzIikKcHJpbnQoCiAgZGF0YSAlPiUgCiAgZ2dwbG90KGFlcyggeD1IUFYzMy5yZWFkcykpICsgCiAgZ2VvbV9kZW5zaXR5KCkKKQpgYGAKCg==